﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;

namespace 串口调试助手
{
    public partial class Form1 : Form
    {
        string SendMode = "文本模式";
        string ReceiveMode = "文本模式";

        public Form1()
        {
            InitializeComponent();
        }

        private void OpenSerialPort()           //打开串口事件
        {
            try
            {
                serialPort1.PortName = PortName_comboBox.Text;
                serialPort1.BaudRate = Convert.ToInt32(BaudRate_comboBox.Text);
                serialPort1.DataBits = Convert.ToInt32(DataBits_comboBox.Text);
                if (StopBits_comboBox.Text == "1") serialPort1.StopBits = StopBits.One;
                else if (StopBits_comboBox.Text == "1.5") serialPort1.StopBits = StopBits.OnePointFive;
                else if (StopBits_comboBox.Text == "2") serialPort1.StopBits = StopBits.Two;
                if (ParityBits_comboBox.Text == "无") serialPort1.Parity = Parity.None;
                else if (ParityBits_comboBox.Text == "偶校验") serialPort1.Parity = Parity.Odd;
                else if (ParityBits_comboBox.Text == "奇校验") serialPort1.Parity = Parity.Even;

                PortName_comboBox.Enabled = false;
                BaudRate_comboBox.Enabled = false;
                StopBits_comboBox.Enabled = false;
                DataBits_comboBox.Enabled = false;
                ParityBits_comboBox.Enabled = false;

                serialPort1.Open();
                OpenPort_button.Text = "关闭串口";
            }
            catch (Exception err)
            {
                //捕获到异常，创建一个新的对象，之前的不可以再用
                serialPort1 = new System.IO.Ports.SerialPort();
                //刷新COM口选项
                PortName_comboBox.Items.Clear();
                PortName_comboBox.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
                //响铃并显示异常给用户
                System.Media.SystemSounds.Beep.Play();
                //显示异常
                MessageBox.Show("打开失败" + err.ToString(), "提示");

                OpenPort_button.Text = "打开串口";

                PortName_comboBox.Enabled = true;
                BaudRate_comboBox.Enabled = true;
                StopBits_comboBox.Enabled = true;
                DataBits_comboBox.Enabled = true;
                ParityBits_comboBox.Enabled = true;
            }
        }

        private void CloseSerialPort()           //关闭串口事件
        {
            serialPort1.Close();

            OpenPort_button.Text = "打开串口";

            PortName_comboBox.Enabled = true;
            BaudRate_comboBox.Enabled = true;
            StopBits_comboBox.Enabled = true;
            DataBits_comboBox.Enabled = true;
            ParityBits_comboBox.Enabled = true;
        }

        private string  ByteToHEXStr(byte[] bytes)       //字节转HEX
        {
            string hex = " ";
            foreach(byte b in bytes)
            {
                hex += "0x" + b.ToString("X2") + " ";
            }
            return hex;
        }

        private byte[] StrToHEXbyte(string hexStr)      //HEX转字节
        {
            hexStr = hexStr.Replace(" ", "");//清除空格
            List<byte> list = new List<byte>();

            for(int i = 0;i<(Send_textBox.Text.Length - Send_textBox.Text.Length % 2) / 2;i++)
            {
                list.Add(Convert.ToByte(Send_textBox.Text.Substring(i * 2, 2), 16));
            }

            if(Send_textBox.Text.Length % 2 != 0)//数据个数为奇数
            {
                list.Add(Convert.ToByte(Send_textBox.Text.Substring(Send_textBox.Text.Length - 1, 1), 16));
            }
            byte[] returnBytes = list.ToArray();

            return returnBytes;
        }

        private void Form1_Load(object sender, EventArgs e)             //窗口加载事件
        {
            /*串口设置默认参数*/
            BaudRate_comboBox.Text = "9600";
            StopBits_comboBox.Text = "1";
            DataBits_comboBox.Text = "8";
            ParityBits_comboBox.Text = "无";
            RecelveMode_comboBox.Text = "文本模式";
            SendMode_comboBox.Text = "HEX模式";

        }

        private void comboBox1_DropDown(object sender, EventArgs e)     //串口号下拉事件
        {
            //搜索电脑可用串口,并显示
            string[] Ports = System.IO.Ports.SerialPort.GetPortNames();
            PortName_comboBox.Items.Clear();
            PortName_comboBox.Items.AddRange(Ports);
        }

        private void OpenPort_button_Click(object sender, EventArgs e)  //打开按钮点击事件
        {
            if(OpenPort_button.Text == "打开串口")
            {
                OpenSerialPort();
            }
            else if(OpenPort_button.Text == "关闭串口")
            {
                CloseSerialPort();
            }
        }

        protected override void DefWndProc(ref Message m)       //USB拔出事件
        {

            if (m.Msg == 0x0219)        //WM_DEVICECHANGE
            {
                if (m.WParam.ToInt32() == 0x8004)
                {
                    if (OpenPort_button.Text == "关闭串口" && serialPort1.IsOpen == false)
                    {
                        CloseSerialPort();      //USB异常拔出，关闭串口
                        PortName_comboBox.Items.Clear();
                    }
                }
            }
            base.DefWndProc(ref m);
        }

            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)//串口接收回调函数
        {
            if(serialPort1.IsOpen)
            {
                int Len = serialPort1.BytesToRead;
                byte[] DataReceive = new byte[Len];
                serialPort1.Read(DataReceive, 0, Len);
                string HEXstr = " ";
                Invoke((new Action(() => //C# 3.0以后代替委托的新方法
                {
                    if (ReceiveMode == "HEX模式")
                    {
                        HEXstr = ByteToHEXStr(DataReceive);//字节转HEX
                    }
                    else if (ReceiveMode == "文本模式")
                    {
                        HEXstr = Encoding.Default.GetString(DataReceive);//Byte值根据ASCII码表转为 String
                    }
                    HEXstr = ">>" + System.DateTime.Now.ToString("T") + System.Environment.NewLine + HEXstr + System.Environment.NewLine;
                    Receive_textBox.AppendText(HEXstr);//追加数据
                })));
            }
        }

        private void RecelveMode_comboBox_SelectedIndexChanged(object sender, EventArgs e)//接收模式选择事件
        {
            if(RecelveMode_comboBox.Text == "文本模式")
            {
                ReceiveMode = "文本模式";
            }
            else if (RecelveMode_comboBox.Text == "HEX模式")
            {
                ReceiveMode = "HEX模式";
            }
        }

        private void ReceMenuCopy_Click(object sender, EventArgs e)//复制接受框内容事件
        {
            Receive_textBox.Copy();
        }

        private void ReceMenuClear_Click(object sender, EventArgs e)//清空接收框事件
        {
            Receive_textBox.Clear();
        }

        private void SendCopyText_Click(object sender, EventArgs e)//发送框复制事件
        {
            Send_textBox.Copy();
        }

        private void SendPasteText_Click(object sender, EventArgs e)//发送框粘贴事件
        {
            Send_textBox.Paste();
        }

        private void SendClearText_Click(object sender, EventArgs e)//发送框清空事件
        {
            Send_textBox.Clear();
        }

        private void Send_button_Click(object sender, EventArgs e)//发送按钮点击事件
        {
            string Send_str = Send_textBox.Text.ToString();

            if(Send_str.Length > 0 && serialPort1.IsOpen)
            {
                if(SendMode == "文本模式")
                {
                    try
                    {
                        serialPort1.Write(Send_str);//字符写入串口
                    }
                    catch (Exception err)
                    {
                        //响铃并显示异常给用户
                        System.Media.SystemSounds.Beep.Play();
                        //显示异常
                        MessageBox.Show(err.ToString(), "提示");
                    }
                }
                else if(SendMode == "HEX模式")
                {
                    try
                    {
                        serialPort1.Write(StrToHEXbyte(Send_str), 0, StrToHEXbyte(Send_str).Length);
                    }
                    catch (Exception err)
                    {
                        //响铃并显示异常给用户
                        System.Media.SystemSounds.Beep.Play();
                        //显示异常
                        MessageBox.Show(err.ToString(), "提示");
                    }
                }   
            }
        }

        private void SendMode_comboBox_SelectedIndexChanged(object sender, EventArgs e)//发送模式选择事件
        {
            if (SendMode_comboBox.Text == "文本模式")
            {
                SendMode = "文本模式";
            }
            else if (SendMode_comboBox.Text == "HEX模式")
            {
                SendMode = "HEX模式";
            }
        }
    }
}
